package com.kensure.shike.weixinpay.service;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import co.kensure.frame.JSBaseService;
import co.kensure.mem.ArithmeticUtils;
import co.kensure.mem.CollectionUtils;
import co.kensure.mem.DateUtils;
import co.kensure.mem.MapUtils;
import co.kensure.mem.NumberUtils;

import com.kensure.basekey.BaseKeyService;
import com.kensure.mycom.config.service.MyConfigService;
import com.kensure.shike.chongzhi.model.SKUserInout;
import com.kensure.shike.chongzhi.service.SKUserInoutService;
import com.kensure.shike.constant.BusiConstant;
import com.kensure.shike.order.model.SKFinPay;
import com.kensure.shike.order.service.SKFinPayASyncService;
import com.kensure.shike.order.service.SKFinPayService;
import com.kensure.shike.user.model.SKUser;
import com.kensure.shike.user.service.SKUserService;
import com.kensure.shike.weixinpay.dao.WXPayinfoDao;
import com.kensure.shike.weixinpay.model.WXPayinfo;
import com.kensure.shike.weixinpay.model.WXPrePay;
import com.kensure.shike.weixinpay.model.WXReadyPay;
import com.kensure.shike.weixinpay.utils.PayUtil;
import com.kensure.shike.weixinpay.utils.UUIDHexGenerator;

@Service
public class WXPayinfoService extends JSBaseService {

	@Resource
	private WXPayinfoDao dao;
	@Resource
	private SKUserInoutService sKUserInoutService;
	@Resource
	private SKUserService sKUserService;
	@Resource
	private BaseKeyService baseKeyService;
	@Resource
	private WeiXinPaymentService weiXinPaymentService;
	@Resource
	private SKFinPayASyncService sKFinPayASyncService;
	@Resource
	private SKFinPayService sKFinPayService;

	public WXPayinfo selectOne(Long id) {
		return dao.selectOne(id);
	}

	public List<WXPayinfo> selectByIds(Collection<Long> ids) {
		return dao.selectByIds(ids);
	}

	public List<WXPayinfo> selectByWhere(Map<String, Object> parameters) {
		return dao.selectByWhere(parameters);
	}

	public long selectCountByWhere(Map<String, Object> parameters) {
		return dao.selectCountByWhere(parameters);
	}

	public boolean insert(WXPayinfo obj) {
		super.beforeInsert(obj);
		obj.setId(baseKeyService.getKey("wx_payinfo"));
		return dao.insert(obj);
	}

	public boolean update(WXPayinfo obj) {
		super.beforeUpdate(obj);
		return dao.update(obj);
	}

	public boolean updateByMap(Map<String, Object> params) {
		return dao.updateByMap(params);
	}

	/**
	 * 新增订单支付的信息
	 * 
	 * @param orderid
	 */
	public WXPrePay addOrder(Long orderid, double jine, String spbill_create_ip) {
		WXReadyPay readyPay = new WXReadyPay();
		SKFinPay order = sKFinPayService.selectOne(orderid);
		readyPay.setBody(order.getCode());
		readyPay.setJine(jine);
		readyPay.setSpbill_create_ip(spbill_create_ip);
		readyPay.setOrderid(orderid);
		readyPay.setPaytype("DD");
		readyPay.setUserid(order.getUserid());
		WXPrePay wxprepay = unitPay(readyPay);
		return wxprepay;
	}

	/**
	 * 新增会员费支付的信息
	 * 
	 * @param orderid
	 */
	public WXPrePay addVip(Long orderid, String spbill_create_ip) {
		WXReadyPay readyPay = new WXReadyPay();
		SKUserInout order = sKUserInoutService.selectOne(orderid);
		readyPay.setBody("会员费");
		readyPay.setJine(order.getJine());
		readyPay.setSpbill_create_ip(spbill_create_ip);
		readyPay.setOrderid(orderid);
		readyPay.setPaytype("VIP");
		readyPay.setUserid(order.getUserid());
		WXPrePay wxprepay = unitPay(readyPay);
		wxprepay.setRemark("会员费用:" + order.getJine());
		return wxprepay;
	}

	/**
	 * 新增会员充值的信息
	 * 
	 * @param orderid
	 */
	public WXPrePay addChongzhi(Long orderid, String spbill_create_ip) {
		WXReadyPay readyPay = new WXReadyPay();
		SKUserInout order = sKUserInoutService.selectOne(orderid);
		readyPay.setBody("充值");
		readyPay.setJine(order.getJine());
		readyPay.setSpbill_create_ip(spbill_create_ip);
		readyPay.setOrderid(orderid);
		readyPay.setPaytype("CZ");
		readyPay.setUserid(order.getUserid());
		WXPrePay wxprepay = unitPay(readyPay);
		wxprepay.setRemark("充值:" + order.getJine());
		return wxprepay;
	}

	/**
	 * 新增会员费提现支付的信息
	 * 
	 * @param orderid
	 */
	public WXPayinfo addTixian(Long orderid, String spbill_create_ip) {
		WXReadyPay readyPay = new WXReadyPay();
		SKUserInout order = sKUserInoutService.selectOne(orderid);
		readyPay.setBody("提现");
		readyPay.setJine(order.getJine());
		readyPay.setSpbill_create_ip(spbill_create_ip);
		readyPay.setOrderid(orderid);
		readyPay.setUserid(order.getUserid());
		WXPayinfo wxprepay = unitTixian(readyPay);
		return wxprepay;
	}

	/**
	 * 这个是统一订单的通用方法
	 * 
	 * @param readyPay
	 * @return
	 */
	private WXPrePay unitPay(WXReadyPay readyPay) {
		String mch_id = MyConfigService.getMyConfig("weixin_mchid").getVal();// 商户号
		String appid = MyConfigService.getMyConfig("weixin_appid").getVal();// 小程序appid

		SKUser user = sKUserService.selectOne(readyPay.getUserid());

		String nonce_str = UUIDHexGenerator.generate();// 随机字符串
		String out_trade_no = genOrderCode(mch_id);// 商户订单id

		WXPayinfo paymentPo = new WXPayinfo();
		paymentPo.setAppid(appid);
		paymentPo.setMch_id(mch_id);
		paymentPo.setNonce_str(nonce_str);
		paymentPo.setOrderid(readyPay.getOrderid() + "");
		paymentPo.setPaytype(readyPay.getPaytype());

		String total_fee = (int) ArithmeticUtils.mul(readyPay.getJine(), 100, 0) + "";

		paymentPo.setBody(readyPay.getBody());
		paymentPo.setOut_trade_no(out_trade_no);
		paymentPo.setTotal_fee(total_fee);
		paymentPo.setSpbill_create_ip(readyPay.getSpbill_create_ip());
		paymentPo.setNotify_url(BusiConstant.wxpay_notify_url);
		paymentPo.setTrade_type(BusiConstant.wxpay_trade_type);
		paymentPo.setOpenid(user.getOpenid());

		Integer weixin_paytime = NumberUtils.parseInteger(MyConfigService.getMyConfig("weixin_paytime").getVal(), 10);

		String time_expire = DateUtils.format(DateUtils.getPastMin(new Date(), weixin_paytime), DateUtils.DATE_FORMAT1);
		paymentPo.setTime_expire(time_expire);
		insert(paymentPo);

		WXPrePay wxprepay = null;
		try {
			wxprepay = weiXinPaymentService.payment(paymentPo);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		paymentPo.setPrepay_id(wxprepay.getPrepayId());
		update(paymentPo);
		return wxprepay;
	}

	/**
	 * 微信企业账号付款给你
	 */
	private WXPayinfo unitTixian(WXReadyPay readyPay) {
		String mch_id = MyConfigService.getMyConfig("weixin_mchid").getVal();// 商户号
		String appid = MyConfigService.getMyConfig("weixin_appid").getVal();// 小程序appid

		SKUser user = sKUserService.selectOne(readyPay.getUserid());

		String nonce_str = UUIDHexGenerator.generate();// 随机字符串
		String out_trade_no = readyPay.getOrderid()+"";// 商户订单id

		WXPayinfo paymentPo = new WXPayinfo();
		paymentPo.setAppid(appid);
		paymentPo.setMch_id(mch_id);
		paymentPo.setNonce_str(nonce_str);
		paymentPo.setOrderid(readyPay.getOrderid() + "");
		paymentPo.setPaytype("TIXIAN");

		String total_fee = (int) ArithmeticUtils.mul(readyPay.getJine(), 100, 0) + "";

		paymentPo.setBody(readyPay.getBody());
		paymentPo.setOut_trade_no(out_trade_no);
		paymentPo.setTotal_fee(total_fee);
		paymentPo.setSpbill_create_ip(readyPay.getSpbill_create_ip());
		paymentPo.setOpenid(user.getOpenid());

		Integer weixin_paytime = NumberUtils.parseInteger(MyConfigService.getMyConfig("weixin_paytime").getVal(), 10);

		String time_expire = DateUtils.format(DateUtils.getPastMin(new Date(), weixin_paytime), DateUtils.DATE_FORMAT1);
		paymentPo.setTime_expire(time_expire);
		insert(paymentPo);

		// 进行提现
		Map<String, String> map = weiXinPaymentService.tixian(paymentPo);

		String return_code = map.get("return_code");// 返回状态码
		String return_msg = map.get("return_msg");// 返回信息
		String result_code = map.get("result_code");// 返回状态码

		System.out.println("请求微信提现接口，返回 code：" + return_code);
		System.out.println("请求微信提现接口，返回 msg：" + return_msg);

		if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
			// 业务结果
			paymentPo.setTrade_state(result_code);
			update(paymentPo);
		} else {

		}

		return paymentPo;
	}

	/**
	 * 微信企业付款查询
	 */
	public Map<String, String> getTixian(Long orderid) {
		String mch_id = MyConfigService.getMyConfig("weixin_mchid").getVal();// 商户号
		String appid = MyConfigService.getMyConfig("weixin_appid").getVal();// 小程序appid

		String nonce_str = UUIDHexGenerator.generate();// 随机字符串
		WXPayinfo paymentPo = new WXPayinfo();
		paymentPo.setAppid(appid);
		paymentPo.setMch_id(mch_id);
		paymentPo.setNonce_str(nonce_str);
		paymentPo.setOrderid(orderid + "");
		paymentPo.setOut_trade_no(orderid + "");
	
		// 查询
		Map<String, String> map = weiXinPaymentService.tixianChaXun(paymentPo);
		return map;
	}
	
	/**
	 * 根据商户订单号获取订单
	 * 
	 * @param out_trade_no
	 * @return
	 */
	public WXPayinfo getByOutTradeNo(String out_trade_no) {
		Map<String, Object> parameters = MapUtils.genMap("out_trade_no", out_trade_no);
		List<WXPayinfo> list = selectByWhere(parameters);
		WXPayinfo info = null;
		if (CollectionUtils.getSize(list) == 1) {
			info = list.get(0);
		}
		return info;
	}

	/**
	 * 支付成功
	 */
	public void paysuc(WXPayinfo info) {
		info.setTrade_state("SUCCESS");
		update(info);
		if ("DD".equalsIgnoreCase(info.getPaytype())) {
			sKFinPayASyncService.successPay(info);
		} else if ("VIP".equalsIgnoreCase(info.getPaytype())) {
			sKUserInoutService.successVip(info);
		} else if ("CZ".equalsIgnoreCase(info.getPaytype())) {
			sKUserInoutService.successChongZhi(info);
		}

	}

	/**
	 * 
	 * @param result_code
	 * @param transaction_id
	 * @param out_trade_no
	 * @return
	 */
	public void callback(String result_code, String transaction_id, String out_trade_no) {
		if ("SUCCESS".equalsIgnoreCase(result_code)) {
			//
			WXPayinfo info = getByOutTradeNo(out_trade_no);
			if (info != null) {
				info.setTransaction_id(transaction_id);
				paysuc(info);
			}
		}
	}

	private String genOrderCode(String mch_id) {
		String today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		String code = PayUtil.createCode(8);
		String out_trade_no = mch_id + today + code;// 商户订单号
		return out_trade_no;
	}
}